﻿using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using LiSAClient.Core.Interfaces;
using LiSAClient.Core.Messages;
using LiSAClient.Core.Viewmodel;

namespace LiSAClient.WpfClient.ViewModel.Frame.Windows
{
    /// <summary>
    /// The abstract base presenter for viewmodels. Must be inherited by windows to enable content control and opening/closing of windows. 
    /// </summary>
    public abstract class BasePresenter : ViewModelBase, IPresenter
    {
        protected BasePresenter()
        {
            this.Waiter = new WaitViewModel();
        }

        public double MaxWindowHeight
        {
            get
            {
                return System.Windows.SystemParameters.MaximizedPrimaryScreenHeight;
            }
        }

        public double MaxWindowWidth
        {
            get
            {
                return System.Windows.SystemParameters.MaximizedPrimaryScreenWidth;
            }
        }

        /// <summary>
        /// Current content (UserControl) being shown in the application.
        /// </summary>
        private ViewModelBase currentContent;

        /// <summary>
        /// Current content (UserControl) being shown in the application.
        /// </summary>
        public ViewModelBase CurrentContent
        {
            get
            {
                return this.currentContent;
            }

            set
            {
                this.Set(() => this.CurrentContent, ref this.currentContent, value);
            }
        }

        private WaitViewModel waiter;

        public WaitViewModel Waiter
        {
            get
            {
                return this.waiter;
            }

            set
            {
                this.Set(() => this.Waiter, ref waiter, value);
            }
        }

        /// <summary>
        /// The event that a closing request has been send.
        /// </summary>
        public event EventHandler ClosingRequest;

        /// <summary>
        /// Notifies the listeners to <see cref="ClosingRequest"/>.
        /// </summary>
        protected void OnClosingRequest()
        {
            if (this.ClosingRequest != null)
            {
                this.ClosingRequest(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Presents the viewmodel, also handling whether it should be in a new window or not.
        /// </summary>
        /// <param name="content">The <see cref="ContentViewModel"/> content to be shown.</param>
        public virtual void PresentContent(ContentViewModel content)
        {
            this.PresentContent(content, true);
        }

        public virtual void PresentContent(ContentViewModel content, bool performOnPresented)
        {
            // If the new viewmodel is null, show nothing.
            if (content == null)
            {
                this.HideContent();
                return;
            }

            // If it is set to be shown in a new window, ask context to open it.
            if (content.ShowInWindow)
            {
                Messenger.Default.Send(new ShowContentInWindowMessage { Content = content, OnLoadedAction = content.OnPresented });
                return;
            }

            // If the current content, already shown, clean it up before replacing.
            if (this.CurrentContent != null)
            {
                this.CurrentContent.Cleanup();
            }

            // Ensure we have the right presenter
            content.SetPresenter(this);

            // Show the new content.
            this.CurrentContent = content;

            // Perform some onPresented action
            if (performOnPresented)
            {
                content.OnPresented();
            }
        }

        public virtual void PerformOnPresented()
        {
            var content = this.CurrentContent as ContentViewModel;

            if (content != null)
            {
                content.OnPresented();
            }
        }

        /// <summary>
        /// Hides the current content.
        /// </summary>
        public virtual void HideContent()
        {
            if (this.CurrentContent != null)
            {
                this.CurrentContent.Cleanup();
            }

            this.CurrentContent = null;
        }

        /// <summary>
        /// Send a closing request. Calls <see cref="OnClosingRequest"/>, which notifies listeners to <see cref="ClosingRequest"/>.
        /// </summary>
        public virtual void SendClosingRequest()
        {
            this.OnClosingRequest();
        }


        /// <summary>
        /// Shows a <see cref="WaitViewModel"/> instead of current content.
        /// </summary>
        /// <param name="waitMessage">Message being shown.</param>
        public virtual void StartWaiting(string waitMessage)
        {
            this.Waiter.IsVisible = true;
            this.Waiter.Text = waitMessage;
        }

        public void UpdateWaitText(string newMessage)
        {
            this.Waiter.Text = newMessage;
        }

        /// <summary>
        /// Changes the current content from the <see cref="WaitViewModel"/> to the waiting content.
        /// </summary>
        public virtual void FinishedWaiting()
        {
            this.Waiter.IsVisible = false;
        }
    }
}
